/** 
 * @Description: 模型时间飞行功能演示
 * @Author: 程前
 * @Date: 2025-02-10 15:11:43
 * @LastEditors: 程前
 * @LastEditTime: 2025-02-12 17:24:41
 */

/**
*  参考资料
*  https://blog.csdn.net/dandan__666/article/details/115293860
*  https://blog.csdn.net/AllBluefm/article/details/137928976
*/



import { Math as CesiumMath, ClockStep, Matrix4, Matrix3, Transforms, PolylineGlowMaterialProperty, Cartesian2, Color, Entity, JulianDate, Viewer, TimeIntervalCollection, TimeInterval, SampledPositionProperty, ClockRange, Cartesian3, VelocityOrientationProperty, HeadingPitchRoll, CompositeProperty } from "cesium"
import { getAssetsFile } from "@/utils";
export default class TimeMotion {
    private viewer: Viewer;
    private entity: Entity;
    constructor(viewer: Viewer) {
        this.viewer = viewer
    }

    /**
     * 初始化事件
     */
    public initEvents() {
        let start = JulianDate.fromDate(new Date());
        // 开始时间  cesium用的JulianDate:代表天文朱利安时间,用的是世界协调时,比北京时间晚8个小时, 加上东8时，就是当前的真正时间
        start = JulianDate.addHours(start, 8, new JulianDate());
        // 结束时间 6分钟
        const center = JulianDate.addSeconds(start, 180, new JulianDate());
        const center2 = JulianDate.addSeconds(start, 200, new JulianDate());
        const stop = JulianDate.addSeconds(start, 360, new JulianDate());
        // 设置时钟范围
        this.viewer.clock.startTime = start.clone();
        this.viewer.clock.stopTime = stop.clone();
        this.viewer.clock.currentTime = start.clone();

        // 循环结束时后续动作
        this.viewer.clock.clockRange = ClockRange.LOOP_STOP;

        // 时间速率控制速度，时间调快多少倍，比如原来用时360秒，调整10倍后，现在用时36秒
        this.viewer.clock.multiplier = 10;
        //给下方时间线设置边界-限启用时间轴时
        this.viewer.timeline && this.viewer.timeline.zoomTo(start, stop);

        const position = new SampledPositionProperty();

        const startPos = Cartesian3.fromDegrees(-90, 20, 10000);
        const centerPos = Cartesian3.fromDegrees(-60, 40, 1000000);
        const centerPos2 = Cartesian3.fromDegrees(-60, 42, 1000000);
        const endPos = Cartesian3.fromDegrees(-120, 30, 3000000);

        position.addSample(start, startPos);
        position.addSample(center, centerPos);
        position.addSample(center2, centerPos2);
        position.addSample(stop, endPos);
        // 添加模型
        this.entity = this.viewer.entities.add({
            // 将实体availability设置为与模拟时间相同的时间间隔。
            availability: new TimeIntervalCollection([new TimeInterval({
                start,
                stop
            })]),
            position, // 计算实体位置属性
            orientation: new VelocityOrientationProperty(position),
            model: {
                uri: getAssetsFile('cesium/models/Cesium_Air.glb'),
                minimumPixelSize: 128,
                scale: 0.2,
            },
            // 路径
            path: {
                show: true,
                resolution: 1,
                material: new PolylineGlowMaterialProperty({
                    glowPower: 0.1,
                    color: Color.RED
                }),
                width: 5
            }
        });
        // 开启运动
        this.viewer.clock.shouldAnimate = true;

        // // 第三人称
        // this.viewer.trackedEntity = this.entity;

        // 第一人称
        this.viewer.scene.preUpdate.addEventListener(this.traceHandler, this)
    }

    /**
    * 追踪当前实体
    */
    private traceHandler() {
        if (!this.entity) {
            return this.viewer.scene.preUpdate.removeEventListener(this.traceHandler, this);
        }
        let center = this.entity.position.getValue(
            this.viewer.clock.currentTime
        );
        let orientation = this.entity.orientation.getValue(
            this.viewer.clock.currentTime
        )
        let transform = Transforms.eastNorthUpToFixedFrame(center);
        transform = Matrix4.fromRotationTranslation(Matrix3.fromQuaternion(orientation), center);
        this.viewer.camera.lookAtTransform(transform, new Cartesian3(-20, 0, 30))
    }

    public destroy() {
        // this.viewer.scene.preUpdate.removeEventListener(this.traceHandler, this);
        this.viewer.clock.shouldAnimate = false;
        this.viewer.clock.clockRange = ClockRange.CLAMPED;
        this.viewer.clock.clockStep = ClockStep.SYSTEM_CLOCK;
        this.viewer.entities.remove(this.entity)
        this.entity = null
    }
}